#include <common/macro/build.h>

#include <query/query.h>
#include <query/filter.h>
#include <query/result.h>
#include <query/iterator.h>
#include <query/commands/select.h>

#include <storage/storage.h>

API_LIBLOCAL result_e query_select_iterator_openpage(query_t *query, page_number_t page_number, page_t **page) {
	storage_page_readlock(query->storage, page_number);
	storage_page_read(query->storage, page_number, page);
	storage_page_rwunlock(query->storage, page_number);

	return RESULT_OK;
}

API_LIBLOCAL result_e query_select_iterator_closepage(query_t *query, page_number_t page_number, page_t *page) {
	page_destroy(page);
	return RESULT_OK;
}

API_LIBLOCAL result_e query_select_execute(query_t *query) {
	result_e result;

	result = query_iterator_prepare(query, query_select_iterator_openpage, query_select_iterator_closepage);
	if (result != RESULT_OK)
		return result;

	return query_filter_prepare(query);
}

API_LIBLOCAL result_e query_select_step(query_t *query) {
	result_e result;

	while ((result = query_iterator_step(query)) == RESULT_OK) {
		/* 1. Verify visibility. */
		if (!query_filter_tuple_visible_create(query, query->iterator.tuple))
			continue;
		if (!query_filter_tuple_visible_delete(query, query->iterator.tuple))
			continue;
		
		/* 2. Verify predicates. */
		if (!query_filter_tuple_predicates(query))
			continue;

		break;
	}

	return result;
}

API_LIBLOCAL result_e query_select_finalize(query_t *query) {
	query_filter_finalize(query);
	return query_iterator_finalize(query);
}
